/*  yALB - Yet Another List Builder (roster Editor for Wargames/tabletop games).
    Copyright (C) 2008-2012  Daniel Ricardo Castro Alvarado

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/


#include "structreader.h"
#include "collections/errorhandler.h"
#include "filestructs.h"
#include "other/functions.h"
#include "objectactions.h"
#include "other/filestructs.h"

#include <QMessageBox>
#include <QFile>
#include <QStringList>
#include <QDebug>

const int MaxDecimals = 1;

StructReader::StructReader(QXmlStreamReader &reader) {
    this->reader = &reader;
}

FileInformation StructReader::readFileInformation() {
    FileInformation information;
    while(reader->readNextStartElement()) {
        if(reader->name() == "name")
            information.name = reader->readElementText();
        else if(reader->name() == "creator")
            information.creator = reader->readElementText();
        else if(reader->name() == "version")
            information.version = reader->readElementText();
        else if(reader->name() == "website")
            information.website = reader->readElementText();
        else if(reader->name() == "comments")
            information.comments = reader->readElementText();
        else
            reader->skipCurrentElement();
    }

    return information;
}

GameCategory StructReader::readUnitCategory(QString &key) {
    GameCategory category;
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            category.setName(reader->readElementText());
        else if(reader->name() == "key")
            key = reader->readElementText();
        else if (reader->name() == "numeric_limit")
            category.setNumericLimit(reader->readElementText().toInt());
        else if (reader->name() == "points_limit")
            category.setPointLimit(reader->readElementText().toInt());
        else if (reader->name() == "percentage_limit")
            category.setPercentageLimit(reader->readElementText().toInt());
        else
            reader->skipCurrentElement();
    }
    return category;
}

GameCategory StructReader::readItemCategory(QString &key) {
    GameCategory category;
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            category.setName(reader->readElementText());
        else if(reader->name() == "key")
            key = reader->readElementText();
        else if (reader->name() == "numeric_limit")
            category.setNumericLimit(reader->readElementText().toInt());
        else if (reader->name() == "points_limit")
            category.setPointLimit(reader->readElementText().toInt());
        else if (reader->name() == "percentage_limit")
            category.setPercentageLimit(reader->readElementText().toInt());
        else
            reader->skipCurrentElement();
    }
    return category;
}

GameCategory StructReader::readOptionCategory(QString &key) {
    GameCategory category;
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            category.setName(reader->readElementText());
        else if(reader->name() == "key")
            key = reader->readElementText();
        else if (reader->name() == "numeric_limit")
            category.setNumericLimit(reader->readElementText().toInt());
        else if (reader->name() == "points_limit")
            category.setPointLimit(reader->readElementText().toInt());
        else if (reader->name() == "percentage_limit")
            category.setPercentageLimit(reader->readElementText().toInt());
        else
            reader->skipCurrentElement();
    }
    return category;
}

Column StructReader::readColumn(QString &key) {
    Column col;
    col.visible = reader->attributes().value("visible").toString() == "yes";
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            col.setName(reader->readElementText());
        else if(reader->name() == "default_value")
            col.defaultValue = reader->readElementText();
        else if (reader->name() == "default_value_mask")
            col.defaultValueAs = reader->readElementText();
        else if (reader->name() == "key")
            key = reader->readElementText();
        else
            reader->skipCurrentElement();
    }
    return col;
}

GameProperty StructReader::readUnitProperty(QString &key) {
    GameProperty property;
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            property.setName(reader->readElementText());
        else if(reader->name() == "default_value")
            property.defaultValue = reader->readElementText();
        else if(reader->name() == "key")
            key = reader->readElementText();
        else
            reader->skipCurrentElement();
    }
    return property;
}

GameProperty StructReader::readItemProperty(QString &key) {
    GameProperty property;
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            property.setName(reader->readElementText());
        else if(reader->name() == "default_value")
            property.defaultValue = reader->readElementText();
        else if(reader->name() == "key")
            key = reader->readElementText();
        else
            reader->skipCurrentElement();
    }
    return property;
}

GameProperty StructReader::readOptionProperty(QString &key) {
    GameProperty property;
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            property.setName(reader->readElementText());
        else if(reader->name() == "default_value")
            property.defaultValue = reader->readElementText();
        else if(reader->name() == "key")
            key = reader->readElementText();
        else
            reader->skipCurrentElement();
    }
    return property;
}

Actions StructReader::readActions() {
    Actions ret;
    while(reader->readNextStartElement()) {
        if(reader->name() == "action") {
            // \FIXME: Incorrect cast from int
            ObjectAction::ActionType type = (ObjectAction::ActionType)reader->attributes().value("type").toString().toUShort();
            QSharedPointer<ObjectAction> action(ObjectAction::createAction(type));
            action->readFromFile(reader);
            ret.append(action);
        } else
            reader->skipCurrentElement();
    }
    return ret;
}

UnitOption StructReader::readOption(QString &key, QString& inherits) {
    UnitOption option;
    option.category = reader->attributes().value("category").toString();
    option.state = GameStructs::getOptionStateFromInt(reader->attributes().value("initial_state").toString().toInt());
    inherits = reader->attributes().value("inherits").toString();
#ifdef UNIT_OPTION_INHERITED_KEY
    option.inheritedKey = inherits;
#endif

    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            option.setName(reader->readElementText());
        else if(reader->name() == "key")
            key = reader->readElementText();
        else if(reader->name() == "required")
            option.required = reader->readElementText();
        else if(reader->name() == "cost_per_model")
            option.costPerMin = reader->readElementText() == "yes";
        else if(reader->name() == "actions") {
            option.actions = readActions();
        }
        else if(reader->name() == "cost")
            option.setCost((float)Functions::trimDecimals(reader->readElementText().toDouble(), MaxDecimals));
        else if(reader->name() == "properties") {
            option.properties = readProperties();
        } else
            reader->skipCurrentElement();
    }

    return option;
}

GameItem StructReader::readItem(QString& key) {
    GameItem item;
    item.category = reader->attributes().value("category").toString();
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            item.setName(reader->readElementText());
        else if(reader->name() == "key")
            key = reader->readElementText();
        else if(reader->name() == "cost")
            item.setCost((float)Functions::trimDecimals(reader->readElementText().toDouble(), MaxDecimals));
        else if(reader->name() == "cost_per_model")
            item.costPerMin = reader->readElementText() == "yes";
        else if(reader->name() == "max_number")
            item.setMaximumNumber(reader->readElementText().toInt());
        else if(reader->name() == "actions") {
            item.actions = readActions();
        } else if(reader->name() == "properties") {
            item.properties = readProperties();
        } else
            reader->skipCurrentElement();
    }
    return item;
}

QHash<QString, InheritedCategoryData> StructReader::readItemLimits() {
    return readInheritedItemCategoryData();
}

Unit StructReader::readUnit(QString& key, QHash<QString, QHash<QString, QString> > *inheritedOptions) {
    Unit unit;

    unit.category = reader->attributes().value("category").toString();

    while(reader->readNextStartElement()) {
        if(reader->name() == "name")
            unit.setName(reader->readElementText());
        else if(reader->name() == "key")
            key = reader->readElementText();
        else if(reader->name() == "description")
            unit.description = reader->readElementText();
        else if(reader->name() == "flags")
            unit.flags = Unit::UnitFlags(reader->readElementText().toInt());
        else if(reader->name() == "minimum_size")
            unit.setMinimumSize(reader->readElementText().toUInt());
        else if(reader->name() == "maximum_size")
            unit.setMaximumSize(reader->readElementText().toUInt());
        else if(reader->name() == "cost")
            unit.setCost((float)Functions::trimDecimals(reader->readElementText().toDouble(), MaxDecimals));
        else if(reader->name() == "allowed_items")
            unit.allowedItems = reader->readElementText().split(',');
        else if(reader->name() == "item_limits")
            unit.itemLimits = readItemLimits();
        else if(reader->name() == "cells")
            unit.cells = readCells();
        else if(reader->name() == "options") {
            QString optionKey;
            QString inheritedKey;
            while(reader->readNextStartElement()) {
                // \FIXME: This could be done wrong if options are read before the key!
                if(reader->name() == "option") {
                    unit.options.add(readOption(optionKey, inheritedKey), optionKey);
                    if(inheritedOptions && !inheritedKey.isEmpty())
                        (*inheritedOptions)[key][optionKey] = inheritedKey;
                } else
                    reader->skipCurrentElement();
            }
        } else if(reader->name() == "properties")
            unit.properties = readProperties();
        else
            reader->skipCurrentElement();
    }
    return unit;
}

GlobalText StructReader::readGlobalText(QString &key) {
    GlobalText gText;
    while (reader->readNextStartElement()) {
        if (reader->name() == "name")
            gText.setName(reader->readElementText());
        else if(reader->name() == "key")
            key = reader->readElementText();
        else if(reader->name() == "text")
            gText.text = reader->readElementText();
        else
            reader->skipCurrentElement();
    }
    return gText;
}

CategoryDataHash StructReader::readInheritedUnitCategoryData() {
    CategoryDataHash data;

    while(reader->readNextStartElement()) {
        if(reader->name() == "element") {
            InheritedCategoryData e;
            QString key = reader->attributes().value("key").toString();

            while(reader->readNextStartElement()) {
                if(reader->name() == "numeric_limit")
                    e.numericLimit = reader->readElementText().toUInt();
                else if(reader->name() == "percentage_limit")
                    e.percentageLimit = reader->readElementText().toUInt();
                else if(reader->name() == "point_limit")
                    e.pointLimit = reader->readElementText().toUInt();
                else
                    reader->skipCurrentElement();
            }

            if(!key.isEmpty())
                data.insert(key, e);
        } else
            reader->skipCurrentElement();
    }

    return data;
}

CategoryDataHash StructReader::readInheritedItemCategoryData() {
    CategoryDataHash data;

    while(reader->readNextStartElement()) {
        if(reader->name() == "element") {
            InheritedCategoryData e;
            QString key = reader->attributes().value("key").toString();

            while(reader->readNextStartElement()) {
                if(reader->name() == "numeric_limit")
                    e.numericLimit = reader->readElementText().toUInt();
                else if(reader->name() == "percentage_limit")
                    e.percentageLimit = reader->readElementText().toUInt();
                else if(reader->name() == "point_limit")
                    e.pointLimit = reader->readElementText().toUInt();
                else
                    reader->skipCurrentElement();
            }
            if(!key.isEmpty())
                data.insert(key, e);
        } else
            reader->skipCurrentElement();
    }

    return data;
}

CategoryDataHash StructReader::readInheritedOptionCategoryData() {
    CategoryDataHash data;

    while(reader->readNextStartElement()) {
        if(reader->name() == "element") {
            InheritedCategoryData e;
            QString key = reader->attributes().value("key").toString();

            while(reader->readNextStartElement()) {
                if(reader->name() == "numeric_limit")
                    e.numericLimit = reader->readElementText().toUInt();
                else if(reader->name() == "percentage_limit")
                    e.percentageLimit = reader->readElementText().toUInt();
                else if(reader->name() == "point_limit")
                    e.pointLimit = reader->readElementText().toUInt();
                else
                    reader->skipCurrentElement();
            }

            if(!key.isEmpty())
                data.insert(key, e);
        } else
            reader->skipCurrentElement();
    }

    return data;
}

QHash<QString, InheritedItemData> StructReader::readInheritedItemData() {
    QHash<QString, InheritedItemData> data;

    while(reader->readNextStartElement()) {
        if(reader->name() == "element") {
            InheritedItemData e;
            QString key = reader->attributes().value("key").toString();

            while(reader->readNextStartElement()) {
                if(reader->name() == "cost")
                    e.cost = (float)Functions::trimDecimals(reader->readElementText().toDouble(), MaxDecimals);
                else if(reader->name() == "maximum_number")
                    e.maxNumber = reader->readElementText().toUInt();
                else
                    reader->skipCurrentElement();
            }

            if(!key.isEmpty())
                data.insert(key, e);
        } else
            reader->skipCurrentElement();
    }

    return data;
}

QHash<QString, InheritedOptionData> StructReader::readInheritedOptionData() {
    QHash<QString, InheritedOptionData> data;

    while(reader->readNextStartElement()) {
        if(reader->name() == "element") {
            InheritedOptionData e;
            QString key = reader->attributes().value("key").toString();

            while(reader->readNextStartElement()) {
                if(reader->name() == "cost")
                    e.cost = (float)Functions::trimDecimals(reader->readElementText().toDouble(), MaxDecimals);
                else
                    reader->skipCurrentElement();
            }

            if(!key.isEmpty())
                data.insert(key, e);
        } else
            reader->skipCurrentElement();
    }

    return data;
}

bool StructReader::isValidGameFile(QXmlStreamReader &reader) {
    // Returns true if it has a valid Game File header
    // This function requires the reader is at the start of the file

    QString version = "";
    if(reader.lineNumber() == 1 && reader.readNextStartElement() && reader.name() == "yALBGameEditor") {
        version = reader.attributes().value("version").toString();
        if(version == "0.1")
            return true;
    }
    return false;
}

bool StructReader::isValidGameFile(const QString &fileName) {
    QFile file(fileName);

    if(file.open(QFile::ReadOnly)) {
        QXmlStreamReader reader(&file);
        bool result = isValidGameFile(reader);
        file.close();
        return result;
    }
    return false;
}

bool StructReader::isValidArmyFile(QXmlStreamReader &reader) {
    // Returns true if it has a valid Army File header
    // This function requires the reader is at the start of the file

    QString version = "";
    if(reader.lineNumber() == 1 && reader.readNextStartElement() && reader.name() == "yALBArmyEditor") {
        version = reader.attributes().value("version").toString();
        if(version == "0.1")
            return true;
    }
    return false;
}

bool StructReader::isValidArmyFile(const QString &fileName) {
    QFile file(fileName);

    if(file.open(QFile::ReadOnly)) {
        QXmlStreamReader reader(&file);
        bool result = isValidArmyFile(reader);
        file.close();
        return result;
    }
    return false;
}

StructReader::ReadResult StructReader::readGameFile(GameFileStructs &fileStructs, FileInformation &information,
                                                      const QString &fileName, QWidget *parent, bool removeAll) {
    QFile file(fileName);
    if(file.open(QFile::ReadOnly)) {
        QXmlStreamReader reader(&file);
        StructReader sr(reader);

        if(isValidGameFile(reader)) {
            Q_ASSERT(fileStructs.columns && fileStructs.globalTexts && fileStructs.itemCategories &&
                     fileStructs.itemProperties && fileStructs.items && fileStructs.optionCategories &&
                     fileStructs.optionProperties && fileStructs.options && fileStructs.unitCategories &&
                     fileStructs.unitProperties);
            if(removeAll)
                fileStructs.clearAll();

            fileStructs.setShowMessages(false);
            //QList<ErrorHandler*> newHandlerList;
            QList<ErrorHandler*> oldHandlerList;

            ListErrorHandler *handler = new ListErrorHandler();

            /*ErrorHandler* itemCategoryHandler = new ErrorHandler();
            ErrorHandler* optionCategoryHandler = new ErrorHandler();
            ErrorHandler* unitCategoryHandler = new ErrorHandler();
            ErrorHandler* columnHandler = new ErrorHandler();
            ErrorHandler* itemPropertyHandler = new ErrorHandler();
            ErrorHandler* optionPropertyHandler = new ErrorHandler();
            ErrorHandler* unitPropertyHandler = new ErrorHandler();
            ErrorHandler* itemHandler = new ErrorHandler();
            ErrorHandler* optionHandler = new ErrorHandler();
            ErrorHandler* globalTextHandler = new ErrorHandler();*/

            // setErrorHandler() returns the previous handler, so fill oldHandlerList and use the new handlers
            oldHandlerList.append(fileStructs.itemCategories->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.optionCategories->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.unitCategories->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.columns->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.itemProperties->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.optionProperties->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.unitProperties->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.items->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.options->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.globalTexts->setErrorHandler(handler));

            while(reader.readNextStartElement()) {
                QString key = "";

                if(reader.name() == "information") {
                    information = sr.readFileInformation();
                } else if(reader.name() == "unit_category") {
                    fileStructs.unitCategories->add(sr.readUnitCategory(key), key);
                } else if(reader.name() == "item_category") {
                    fileStructs.itemCategories->add(sr.readItemCategory(key), key);
                } else if(reader.name() == "option_category") {
                    fileStructs.optionCategories->add(sr.readOptionCategory(key), key);
                } else if(reader.name() == "column") {
                    fileStructs.columns->add(sr.readColumn(key), key);
                } else if(reader.name() == "unit_property") {
                    fileStructs.unitProperties->add(sr.readUnitProperty(key), key);
                } else if(reader.name() == "item_property") {
                    fileStructs.itemProperties->add(sr.readItemProperty(key), key);
                } else if(reader.name() == "option_property") {
                    fileStructs.optionProperties->add(sr.readOptionProperty(key), key);
                } else if(reader.name() == "option") {
                    QString inheritedKey;
                    fileStructs.options->add(sr.readOption(key, inheritedKey), key);
                } else if(reader.name() == "item") {
                    fileStructs.items->add(sr.readItem(key), key);
                } else if(reader.name() == "global_text") {
                    fileStructs.globalTexts->add(sr.readGlobalText(key), key);
                } else
                    reader.skipCurrentElement();
            }

            QStringList errors(handler->getAllErrors());

            if(errors.count() > 0) {
                QMessageBox mess(QMessageBox::Warning, tr("Problems while loading file"), tr("The Game File was loaded with some errors. Click on details for more information"),
                                 QMessageBox::Ok, parent);
                mess.setDetailedText(errors.join("\n"));
                mess.exec();
            }

            file.close();

            fileStructs.itemCategories->setErrorHandler(oldHandlerList.at(0));
            fileStructs.optionCategories->setErrorHandler(oldHandlerList.at(1));
            fileStructs.unitCategories->setErrorHandler(oldHandlerList.at(2));
            fileStructs.columns->setErrorHandler(oldHandlerList.at(3));
            fileStructs.itemProperties->setErrorHandler(oldHandlerList.at(4));
            fileStructs.optionProperties->setErrorHandler(oldHandlerList.at(5));
            fileStructs.unitProperties->setErrorHandler(oldHandlerList.at(6));
            fileStructs.items->setErrorHandler(oldHandlerList.at(7));
            fileStructs.options->setErrorHandler(oldHandlerList.at(8));
            fileStructs.globalTexts->setErrorHandler(oldHandlerList.at(9));

            delete handler;

            fileStructs.setShowMessages(true);
            return StructReader::Success;

        } else {
            QMessageBox::critical(parent, tr("Error"), tr("The file could not be loaded because it is not a compatible Game File"));
            file.close();
            return StructReader::IncompatibleGameFile;
        }
    } else {
        QMessageBox::critical(parent, tr("Error"), tr("There was a problem while attempting to open Game File"));
        return StructReader::FileAccessError;
    }
}

StructReader::ReadResult StructReader::readArmyFile(ArmyFileStructs &fileStructs,
                                                      FileInformation &armyInformation,
                                                      const QString &armyFile,
                                                      QWidget *parent,
                                                      QHash<QString, QHash<QString, QString> > *inheritedOptions,
                                                      bool removeAll) {

    QFile file(armyFile);
    if(file.open(QFile::ReadOnly)) {
        QXmlStreamReader reader(&file);
        StructReader sr(reader);

        if(isValidArmyFile(reader)) {
            Q_ASSERT(fileStructs.globalTexts && fileStructs.itemCategories &&
                     fileStructs.items && fileStructs.optionCategories &&
                     fileStructs.options && fileStructs.unitCategories &&
                     fileStructs.units && fileStructs.inheritedItemCategoryData &&
                     fileStructs.inheritedItemData && fileStructs.inheritedOptionCategoryData &&
                     fileStructs.inheritedOptionData && fileStructs.inheritedUnitCategoryData);

            fileStructs.setShowMessages(false);

            QList<ErrorHandler*> oldHandlerList;

            ListErrorHandler *handler = new ListErrorHandler();

            // setErrorHandler() returns the previous handler, so fill oldHandlerList and use the new handlers
            oldHandlerList.append(fileStructs.itemCategories->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.optionCategories->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.unitCategories->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.items->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.options->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.globalTexts->setErrorHandler(handler));
            oldHandlerList.append(fileStructs.units->setErrorHandler(handler));

            if(removeAll)
                fileStructs.clearAll();

            while(reader.readNextStartElement()) {
                QString key = "";

                if(reader.name() == "information") {
                    armyInformation = sr.readFileInformation();
                } else if(reader.name() == "unit_category") {
                    fileStructs.unitCategories->add(sr.readUnitCategory(key), key);
                } else if(reader.name() == "item_category") {
                    fileStructs.itemCategories->add(sr.readItemCategory(key), key);
                } else if(reader.name() == "option_category") {
                    fileStructs.optionCategories->add(sr.readOptionCategory(key), key);
                } else if(reader.name() == "option") {
                    QString inheritedKey;
                    fileStructs.options->add(sr.readOption(key, inheritedKey), key);
                } else if(reader.name() == "item") {
                    fileStructs.items->add(sr.readItem(key), key);
                } else if(reader.name() == "unit") {
                    fileStructs.units->add(sr.readUnit(key, inheritedOptions), key);
                } else if(reader.name() == "global_text") {
                    fileStructs.globalTexts->add(sr.readGlobalText(key), key);
                } else if(reader.name() == "override_unit_categories")
                    *(fileStructs.inheritedUnitCategoryData) = sr.readInheritedUnitCategoryData();
                else if(reader.name() == "override_item_categories")
                    *(fileStructs.inheritedItemCategoryData) = sr.readInheritedItemCategoryData();
                else if(reader.name() == "override_option_categories")
                    *(fileStructs.inheritedOptionCategoryData) = sr.readInheritedOptionCategoryData();
                else if(reader.name() == "override_items")
                    *(fileStructs.inheritedItemData) = sr.readInheritedItemData();
                else if(reader.name() == "override_options")
                    *(fileStructs.inheritedOptionData) = sr.readInheritedOptionData();
                else
                    reader.skipCurrentElement();
            }

            QStringList errors(handler->getAllErrors());

            if(errors.count() > 0) {
                QMessageBox mess(QMessageBox::Warning, tr("Problems while loading file"), tr("The Army File was loaded with some errors. Click on details for more information"),
                                 QMessageBox::Ok, parent);
                mess.setDetailedText(errors.join("\n"));
                mess.exec();
            }

            file.close();

            fileStructs.itemCategories->setErrorHandler(oldHandlerList.at(0));
            fileStructs.optionCategories->setErrorHandler(oldHandlerList.at(1));
            fileStructs.unitCategories->setErrorHandler(oldHandlerList.at(2));
            fileStructs.items->setErrorHandler(oldHandlerList.at(3));
            fileStructs.options->setErrorHandler(oldHandlerList.at(4));
            fileStructs.units->setErrorHandler(oldHandlerList.at(5));
            fileStructs.globalTexts->setErrorHandler(oldHandlerList.at(6));

            delete handler;

            fileStructs.setShowMessages(true);
            return StructReader::Success;

        } else {
            QMessageBox::critical(parent, tr("Error"), tr("The file could not be loaded because it is not a compatible Army File"));
            file.close();
            return StructReader::IncompatibleGameFile;
        }
    } else {
        QMessageBox::critical(parent, tr("Error"), tr("There was a problem while attempting to open Army File"));
        return StructReader::FileAccessError;
    }
}

// Private

QHash<QString, QString> StructReader::readProperties() {
    QHash<QString, QString> properties;
    while (reader->readNextStartElement()) {
        if (reader->name() == "value") {
            QString key = reader->attributes().value("key").toString();
            if(!key.isEmpty())
                properties.insert(key, reader->readElementText());
        } else
            reader->skipCurrentElement();
    }
    return properties;
}

QHash<QString, QString> StructReader::readCells() {
    QHash<QString, QString> cells;
    while(reader->readNextStartElement()) {
        if(reader->name() == "value") {
            QString key = reader->attributes().value("key").toString();
            if(!key.isEmpty())
                cells.insert(key, reader->readElementText());
        } else
            reader->skipCurrentElement();
    }
    return cells;
}
